/**
 * Main function for rubik's cube solver
 *
 * @author Daniel Rogers
 *
 */

#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
#include "cube.h"
#include "cubeIO.h"
#include "heuristicGenerator.h"
#include "utils.h"
#include "idastar.h"

#ifndef TEST

int main(int argc, const char** argv)
{

    //Load in table if already generated
    uint8_t * htables[3];

    if (loadHTables(htables))
    {
        puts("Tables loaded successfully, press enter to continue...");
        getchar();
    }
    else
    {
        //Timers
        clock_t tstart, tend;
        double tex;

        puts("Generating table files");

        //See how long it takes to generate the tables
        tstart = clock();
        generateTables();
        tend = clock();

        tex = (double) (tend - tstart) / CLOCKS_PER_SEC;
        puts("Table generation complete:");
        printf("    Time (s): %.4f\n", tex);

        if (loadHTables(htables))
        {
            puts("Tables loaded successfully");
        }
        else
        {
            puts("Fatal error");
            return 1;
        }
    }

    if (argc > 1)
    {
        Cube start;

        puts("Loading cube state");
        if(loadCubeFromFile(argv[1], &start, htables))
        {
            char res = ida_star(start, htables);
            if(res == 'F')
            {
                puts("Search complete");
            }
            else
            {
                puts("Solution not found");
            }
        }
        else
        {
            puts("Cube state failed to load, cannot continue");
        }
    }
    else
    {
        puts("No cube state file specified, cannot continue.");
    }

    return 0;
}

#else
#include "cubeTests.h"

//Testing main
int main(int argc, const char** argv)
{
    bool passed = true;

    passed &= cubeTestAll();

    if (!passed)
    {
        puts("Tests failed");
        return -1;
    }

    //Load in table if already generated
    uint8_t * htables[3];
    if (loadHTables(htables))
    {
        puts("Tables loaded successfully");
    }
    else
    {
        //Timers
        clock_t tstart, tend;
        double tex;

        puts("Generating table files");

        //See how long it takes to generate the tables
        tstart = clock();
        passed &= generateTables();
        tend = clock();

        tex = (double) (tend - tstart) / CLOCKS_PER_SEC;
        puts("Table generation:");
        printf("    Time (s): %.4f\n", tex);

        if (loadHTables(htables))
        {
            puts("Tables loaded successfully");
        }
    }

    Cube testStar;
    getUnitCube(&testStar);
    Cube tests[7][6];

    permuteAll(testStar, tests[0]);

    for (int x = 1; x < 7; ++x)
    {
        permuteAll(tests[0][x - 1], tests[x]);
    }

    for (int i = 1; i < 7; ++i)
    {
        for (int j = 0; j < 6; ++j)
        {
            bool res = ida_star(tests[i][j], htables);

            if (res)
            {
                puts("Search complete");
            }
            else
            {
                puts("Solution not found");
                break;
            }
        }
    }

    if (argc == 2)
    {
        Cube ld;
        uint8_t corners[8];
        uint8_t edges[12];

        puts("Testing cube state file load");
        passed &= loadCubeFromFile(argv[1], &ld, htables);

        puts("Read in state:");
        decodeCorners(ld.corners, corners);
        decompressEdges(ld.edges, edges);

        for (int i = 0; i < 8; ++i)
        {
            printf("    c[%d]: %d\n", i, corners[i]);
        }
        for (int i = 0; i < 12; ++i)
        {
            printf("    e[%d]: %d\n", i, edges[i]);
        }
        printf("    cspin: %x\n", ld.corner_spin);
        printf("    espin: %x\n", ld.edge_spin);

        char res = ida_star(ld, htables);
        if (res == 'F')
        {
            puts("Search complete");
        }
        else
        {
            puts("Solution not found");
        }
    }
    else
    {
        puts("No cube state test filed specified, skipping test load");
    }

    //Free table memory
    freeHTables(htables);

    if (passed)
    {
        puts("All tests passed");
        return 0;
    }
    else
    {
        puts("Tests failed");
        return -1;
    }

}

#endif /** TEST **/

